﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data.SqlClient;
using SWEN_HMS.Classes;
using System.Globalization;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;

namespace SWEN_HMS.BookingModule
{
    public partial class CheckOut : System.Web.UI.Page
    {
        double invoiceSubTotalAmount = 0.00;
        double invoiceGrandTotalAmount = 0.00;
        double invoiceGST = 0.00;
        int daysOfStay = 0;
        int bookingID = 0;
        int roomNo = 0;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["staffid"] == null)
            {
                Response.Redirect("~/UserModule/Login.aspx");
            }
            else if ((Convert.ToString(Session["accessLvl"])) == "No Access")
            {
                Response.Redirect("~/UserModule/Login.aspx");
            }
            else
            {
                if (!Page.IsPostBack)
                {
                    if (Request.QueryString["Room"] != null && Request.QueryString["Room"] != "")
                    {
                        tbxRoomNo.Enabled = false;
                        btnSearch.Enabled = false;
                        RequiredFieldValidator1.Enabled = false;

                        tbxRoomNo.Text = Convert.ToString(Request.QueryString["Room"]);

                        Booking bookingInfo = getBookingInfoByRoomID(Convert.ToInt32(tbxRoomNo.Text)); // convert room No. to booking ID
                        if (bookingInfo != null)
                        {
                            bookingID = bookingInfo.bookingID;
                            Invoice invoice = getInvoiceInfo(bookingInfo.bookingID);
                            if (invoice != null)
                            {
                                lblBookingID.Text = Convert.ToString(bookingID);
                                lblGuestName.Text = bookingInfo.firstName + " " + bookingInfo.lastName;
                                lblInvoiceID.Text = Convert.ToString(invoice.invoiceID);
                                lblCheckInDate.Text = bookingInfo.checkIn;
                                lblCheckOut.Text = bookingInfo.checkOut;
                                if (bookingInfo.paymentType == "Cash")
                                {
                                    lblPaymentMode.Text = "Cash";
                                }
                                else if (bookingInfo.paymentType == "Credit Card")
                                {
                                    lblPaymentMode.Text = "Credit Card - " + bookingInfo.cardType;
                                }

                                List<InvoiceItem> invoiceItems = getInvoiceItemsByInvoiceID(invoice.invoiceID, bookingInfo.bookingID);
                                if (invoiceItems != null)
                                {
                                    GridView1.DataSource = invoiceItems;
                                    GridView1.DataBind();

                                    invoiceSubTotalAmount = 0.00;
                                    invoiceGrandTotalAmount = 0.00;
                                    invoiceGST = 0.00;
                                    foreach (InvoiceItem i in invoiceItems)
                                    {
                                        invoiceSubTotalAmount += Convert.ToDouble(i.totalPrice);
                                    }
                                    lblRoomNumber.Text = Convert.ToString(roomNo);
                                    invoiceGST = invoiceSubTotalAmount * 7 / 100;
                                    invoiceGrandTotalAmount = invoiceGST + invoiceSubTotalAmount;
                                    lblFinalCO.Text = DateTime.Now.ToString("dd/MM/yyyy");
                                    Label1.Text = "";


                                }
                                else
                                {
                                    Label1.Text = "No items in invoice!";
                                    lblPaymentMode.Text = "";
                                    GridView1.DataSource = null;
                                    GridView1.DataBind();
                                    invoiceSubTotalAmount = 0.00;
                                    invoiceGrandTotalAmount = 0.00;
                                    invoiceGST = 0.00;
                                }
                            }
                            else
                            {
                                Label1.Text = "Invoice does not exist!";
                                lblPaymentMode.Text = "";
                                GridView1.DataSource = null;
                                GridView1.DataBind();
                                invoiceSubTotalAmount = 0.00;
                                invoiceGrandTotalAmount = 0.00;
                                invoiceGST = 0.00;
                            }
                        }
                        else
                        {
                            Label1.Text = "Booking does not exist!";
                            lblPaymentMode.Text = "";
                            GridView1.DataSource = null;
                            GridView1.DataBind();
                            invoiceSubTotalAmount = 0.00;
                            invoiceGrandTotalAmount = 0.00;
                            invoiceGST = 0.00;
                        }
                    }
                    else
                    {
                        tbxRoomNo.Enabled = true;
                        btnSearch.Enabled = true;
                        RequiredFieldValidator1.Enabled = true;
                        invoiceSubTotalAmount = 0.00;
                        invoiceGrandTotalAmount = 0.00;
                        invoiceGST = 0.00;
                        lblPaymentMode.Text = "";
                    }
                    Label3.Text = String.Format("{0:0.00}", invoiceSubTotalAmount);
                    Label2.Text = String.Format("{0:0.00}", invoiceGrandTotalAmount);
                    Label4.Text = String.Format("{0:0.00}", invoiceGST);

                    ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
                    scriptManager.RegisterPostBackControl(this.Button2);
                }
            }
        }

        public override void VerifyRenderingInServerForm(Control control)
        {

        }

        protected void btnSearch_Click(object sender, EventArgs e)
        {
            tbxRoomNo.Enabled = true;
            btnSearch.Enabled = true;
            RequiredFieldValidator1.Enabled = true;

            Booking bookingInfo = getBookingInfoByRoomID(Convert.ToInt32(tbxRoomNo.Text)); // convert room No. to booking ID

            if (bookingInfo != null)
            {
                bookingID = bookingInfo.bookingID;
                Invoice invoice = getInvoiceInfo(bookingInfo.bookingID);
                if (invoice != null)
                {
                    lblBookingID.Text = Convert.ToString(bookingID);
                    lblGuestName.Text = bookingInfo.firstName + " " + bookingInfo.lastName;
                    lblInvoiceID.Text = Convert.ToString(invoice.invoiceID);
                    lblCheckInDate.Text = bookingInfo.checkIn;
                    lblCheckOut.Text = bookingInfo.checkOut;
                    if (bookingInfo.paymentType == "Cash")
                    {
                        lblPaymentMode.Text = "Cash";
                    }
                    else if (bookingInfo.paymentType == "Credit Card")
                    {
                        lblPaymentMode.Text = "Credit Card - " + bookingInfo.cardType;
                    }

                    List<InvoiceItem> invoiceItems = getInvoiceItemsByInvoiceID(invoice.invoiceID, bookingInfo.bookingID);

                    if (invoiceItems != null)
                    {
                        GridView1.DataSource = invoiceItems;
                        GridView1.DataBind();

                        invoiceSubTotalAmount = 0.00;
                        invoiceGrandTotalAmount = 0.00;
                        invoiceGST = 0.00;
                        foreach (InvoiceItem i in invoiceItems)
                        {
                            invoiceSubTotalAmount += Convert.ToDouble(i.totalPrice);
                        }
                        lblRoomNumber.Text = Convert.ToString(roomNo);
                        invoiceGST = invoiceSubTotalAmount * 7 / 100;
                        invoiceGrandTotalAmount = invoiceGST + invoiceSubTotalAmount;
                        Label1.Text = "";
                        lblFinalCO.Text = DateTime.Now.ToString("dd/MM/yyyy");
                        tbxRoomNo.Enabled = false;
                        btnSearch.Enabled = false;
                        RequiredFieldValidator1.Enabled = false;
                    }
                    else
                    {
                        Label1.Text = "No items in invoice!";
                        GridView1.DataSource = null;
                        GridView1.DataBind();
                        invoiceSubTotalAmount = 0.00;
                        invoiceGrandTotalAmount = 0.00;
                        invoiceGST = 0.00;
                        lblPaymentMode.Text = "";
                    }
                }
                else
                {
                    Label1.Text = "Invoice does not exist!";
                    GridView1.DataSource = null;
                    GridView1.DataBind();
                    invoiceSubTotalAmount = 0.00;
                    invoiceGrandTotalAmount = 0.00;
                    invoiceGST = 0.00;
                    lblPaymentMode.Text = "";
                }
            }
            else
            {
                Label1.Text = "Booking does not exist!";
                invoiceSubTotalAmount = 0.00;
                invoiceGrandTotalAmount = 0.00;
                invoiceGST = 0.00;
                lblPaymentMode.Text = "";
            }
            Label3.Text = String.Format("{0:0.00}", invoiceSubTotalAmount);
            Label2.Text = String.Format("{0:0.00}", invoiceGrandTotalAmount);
            Label4.Text = String.Format("{0:0.00}", invoiceGST);
        }


        public static Booking getBookingInfoByRoomID(int roomID)
        {
            Booking result = null;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "SELECT * FROM Booking WHERE roomNo=@roomNo";
                comm.Parameters.AddWithValue("@roomNo", roomID);
                SqlDataReader dr = comm.ExecuteReader();
                while (dr.Read())
                {
                    DateTime checkInDate = (DateTime)dr["checkIn"];
                    DateTime checkOutDate = (DateTime)dr["checkOut"];

                    if (((string)dr["checkInStatus"] == "True") && (DateTime.Now >= checkInDate))
                    {
                        if (result == null)
                        {
                            result = new Booking();
                        }
                        result.bookingID = (int)dr["bookingID"];
                        result.firstName = (string)dr["firstName"];
                        result.lastName = (string)dr["lastName"];
                        result.checkIn = checkInDate.ToString("dd/MM/yyyy");
                        result.checkOut = checkOutDate.ToString("dd/MM/yyyy");
                        result.paymentType = (string)dr["paymentType"];
                        if (result.paymentType == "Credit Card")
                        {
                            result.cardType = (string)dr["cardType"];
                        }
                    }
                }
                dr.Close();
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return result;
        }

        public List<InvoiceItem> getInvoiceItemsByInvoiceID(int invoiceID, int bookingID)
        {
            List<InvoiceItem> resultSet = null;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "SELECT * FROM InvoiceItem WHERE invoiceID=@invoiceID";
                comm.Parameters.AddWithValue("@invoiceID", invoiceID);
                SqlDataReader dr = comm.ExecuteReader();
                while (dr.Read())
                {
                    if (resultSet == null)
                    {
                        resultSet = new List<InvoiceItem>();
                    }
                    InvoiceItem item = new InvoiceItem();
                    item.invoiceID = (int)dr["invoiceID"];
                    item.itemID = (int)dr["itemID"];
                    item.description = (string)dr["description"];
                    item.quantity = (int)dr["quantity"];
                    item.unitPrice = (decimal)dr["unitPrice"];
                    item.totalPrice = item.quantity * item.unitPrice;
                    resultSet.Add(item);
                }
                dr.Close();

                int noOfDaysByBookingID = 0;
                DateTime checkOutDateFromDBRecord = DateTime.MinValue;
                DateTime checkInDateFromDBRecord = DateTime.MinValue;

                SqlCommand comm1 = new SqlCommand();
                comm1.Connection = conn;
                comm1.CommandText = "SELECT noOfDay, checkOut, checkIn FROM Booking WHERE bookingID=@bookingID";
                comm1.Parameters.AddWithValue("@bookingID", bookingID);
                SqlDataReader dr1 = comm1.ExecuteReader();
                if (dr1.Read())
                {
                    noOfDaysByBookingID = (int)dr1["noOfDay"];
                    checkOutDateFromDBRecord = (DateTime)dr1["checkOut"];
                    checkInDateFromDBRecord = (DateTime)dr1["checkIn"];
                }
                dr1.Close();

                int finalNoOfDays = 0;
                DateTime finalCheckOutDate = checkOutDateFromDBRecord;
                if ((checkOutDateFromDBRecord != DateTime.MinValue) && (checkInDateFromDBRecord != DateTime.MinValue))
                {
                    TimeSpan diff = DateTime.Now - checkInDateFromDBRecord;
                    finalNoOfDays = diff.Days;
                    finalCheckOutDate = DateTime.Now;
                    //if (diff.Days > noOfDaysByBookingID)
                    //{
                    //    finalNoOfDays = diff.Days;
                    //    finalCheckOutDate = DateTime.Now;
                    //}
                    //else if (diff.Days < noOfDaysByBookingID)
                    //{
                    //    finalNoOfDays = diff.Days;
                    //    finalCheckOutDate = DateTime.Now;
                    //}
                    //else
                    //{
                    //    finalNoOfDays = noOfDaysByBookingID;
                    //}
                    daysOfStay = finalNoOfDays;
                }


                SqlCommand comm2 = new SqlCommand();
                comm2.Connection = conn;
                comm2.CommandText = "SELECT cost, roomNo, roomType FROM Room WHERE roomNo IN (SELECT roomNo FROM Booking WHERE bookingID=@bookingID)";
                comm2.Parameters.AddWithValue("@bookingID", bookingID);
                SqlDataReader dr2 = comm2.ExecuteReader();
                if (dr2.Read())
                {
                    if (resultSet == null)
                    {
                        resultSet = new List<InvoiceItem>();
                    }
                    InvoiceItem item = new InvoiceItem();
                    roomNo = (int)dr2["roomNo"];
                    item.description = "Room Type: " + (string)dr2["roomType"];
                    if (finalNoOfDays == 0)
                    {
                        item.quantity = 1;
                    }
                    else
                    {
                        item.quantity = finalNoOfDays;
                    }
                    item.unitPrice = (decimal)dr2["cost"];
                    item.totalPrice = item.quantity * item.unitPrice;
                    resultSet.Add(item);
                }
                dr2.Close();
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return resultSet;
        }

        public static Invoice getInvoiceInfo(int bookingID)
        {
            Invoice result = null;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "SELECT * FROM Invoice WHERE bookingID=@bookingID";
                comm.Parameters.AddWithValue("@bookingID", bookingID);
                SqlDataReader dr = comm.ExecuteReader();
                if (dr.Read())
                {
                    if (result == null && (dr["totalAmount"] == DBNull.Value))
                    {
                        result = new Invoice();
                    }
                    if (result != null)
                    {
                        result.invoiceID = (int)dr["invoiceID"];
                        result.bookingID = bookingID;
                    }
                }
                dr.Close();
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return result;
        }

        protected void Button1_Click(object sender, EventArgs e) // check out and print invoice
        {
            ifCheckOutFinalise();
        }

        protected void Button2_Click(object sender, EventArgs e) // print pdf
        {
            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition", "attachment;filename=AllGuestsInAllRoomsReport.pdf");
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            StringWriter sw = new StringWriter();
            HtmlTextWriter hw = new HtmlTextWriter(sw);
            Panel1.RenderControl(hw);
            GridView1.AllowPaging = false;
            GridView1.RenderControl(hw);
            Panel2.RenderControl(hw);

            StringReader sr = new StringReader(sw.ToString());
            Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
            HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
            PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
            pdfDoc.Open();
            pdfDoc.Add(new Paragraph("Delonix Regia Hotel - Hotel Management System"));
            iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(Server.MapPath("~/Image/HMS_LOGO.jpg"));
            jpg.Alignment = iTextSharp.text.Image.ALIGN_CENTER;
            pdfDoc.Add(jpg);
            htmlparser.Parse(sr);
            pdfDoc.Close();
            Response.Write(pdfDoc);
            Response.End();
        }

        protected void Button3_Click(object sender, EventArgs e) // return to room status
        {
            Response.Redirect("~/BookingModule/RoomAvailability.aspx");
        }

        public static bool finaliseTotalAmtIntoInvoiceDB(int invoiceID, decimal totalAmount)
        {
            bool result = false;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "UPDATE Invoice SET totalAmount=@totalAmount WHERE invoiceID=@invoiceID";
                comm.Parameters.AddWithValue("@totalAmount", totalAmount);
                comm.Parameters.AddWithValue("@invoiceID", invoiceID);
                int ifUpdated = 0;
                ifUpdated = comm.ExecuteNonQuery();
                if (ifUpdated == 1)
                {
                    result = true;
                }
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return result;
        }

        public static bool resetRoomStatuses(int roomNo)
        {
            bool result = false;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "UPDATE Room SET roomStatus=@roomStatus, noOfAdult=@noOfAdult, noOfChild=@noOfChild WHERE roomNo=@roomNo";
                comm.Parameters.AddWithValue("@roomStatus", "Available");
                comm.Parameters.AddWithValue("@noOfAdult", 0);
                comm.Parameters.AddWithValue("@noOfChild", 0);
                comm.Parameters.AddWithValue("@roomNo", roomNo);
                int ifUpdated = 0;
                ifUpdated = comm.ExecuteNonQuery();
                if (ifUpdated == 1)
                {
                    result = true;
                }
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return result;
        }

        public static bool editBookingInfoAfterCheckOut(int bookingID, int noOfDay)
        {
            bool result = false;
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["HMSConnectionString"].ConnectionString;
                conn.Open();
                SqlCommand comm = new SqlCommand();
                comm.Connection = conn;
                comm.CommandText = "UPDATE Booking SET checkOut=@checkOut, noOfDay=@noOfDay WHERE bookingID=@bookingID";
                comm.Parameters.AddWithValue("@checkOut", DateTime.Now);
                comm.Parameters.AddWithValue("@noOfDay", noOfDay);
                comm.Parameters.AddWithValue("@bookingID", bookingID);
                int ifAdded = 0;
                ifAdded = comm.ExecuteNonQuery();
                if (ifAdded == 1)
                {
                    result = true;
                }
                conn.Close();
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            return result;
        }

        protected void ifCheckOutFinalise()
        {
            bool ifAppliedTotalAmountToInvoice = finaliseTotalAmtIntoInvoiceDB(Convert.ToInt32(lblInvoiceID.Text), Convert.ToDecimal(Label2.Text));
            if (ifAppliedTotalAmountToInvoice == true)
            {
                bool ifRoomStatusResetted = resetRoomStatuses(Convert.ToInt32(tbxRoomNo.Text));
                if (ifRoomStatusResetted == true)
                {
                    // change booking info
                    bool ifBookingInfoUpdated = editBookingInfoAfterCheckOut(Convert.ToInt32(lblBookingID.Text), daysOfStay);
                    if (ifBookingInfoUpdated == true)
                    {
                        Button2.Enabled = true;
                        Button2.Visible = true;
                    }
                }
                else
                {
                    Label1.Text = "Unable to reset room status! Please contact administrator for assistance.";
                }
            }
            else
            {
                Label1.Text = "Unable to check out!";
            }
        }
    }
}